//
//  CustomCameraView.swift
//  XGamesLive
//
//  Created by ios on 2024/5/29.
//

import UIKit
import AVFoundation

class CustomCameraView: UIView {
    
    var device : AVCaptureDevice!
    var input : AVCaptureDeviceInput!
    var output : AVCaptureMetadataOutput!
    var videoOutput:  AVCaptureVideoDataOutput!
    var imageOutPut : AVCapturePhotoOutput!
    var session : AVCaptureSession!
    
    var photoSettings :AVCapturePhotoSettings!
    var previewLayer : AVCaptureVideoPreviewLayer!
    
    let sessionQueue = DispatchQueue(label: "session queue",
    attributes: [],
    target: nil)
    
    override init(frame: CGRect) {
        super.init(frame: frame)
       
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    public func startCamera(){
        sessionQueue.async { [unowned self] in
            self.configureSession()
        }
    }
    
    override func layoutSubviews() {
        if self.previewLayer != nil {
//            self.previewLayer.frame = CGRect(x: 0, y: 0, width: self.bounds.width, height: self.bounds.height)
            previewLayer.frame = self.bounds
            if (previewLayer.connection?.isVideoOrientationSupported)! {
                previewLayer.connection?.videoOrientation = UIApplication.shared.statusBarOrientation.videoOrientation ?? .portrait
            }
        }
        
    }
    
    private func configureSession() {
        let availbleDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .front).devices
        device = availbleDevices.first
        
        do {
            // Get an instance of the AVCaptureDeviceInput class using the previous deivce object
            let input = try AVCaptureDeviceInput(device: device)
            
            // Initialize the captureSession object
            session = AVCaptureSession()
            
            // Set the input devcie on the capture session
            session.addInput(input)
            
            // Get an instance of ACCapturePhotoOutput class
            imageOutPut = AVCapturePhotoOutput()
            imageOutPut.isHighResolutionCaptureEnabled = true
            
            // Set the output on the capture session
            session.addOutput(imageOutPut)
            
            // Initialize a AVCaptureMetadataOutput object and set it as the input device
            let captureMetadataOutput = AVCaptureMetadataOutput()
            session.addOutput(captureMetadataOutput)

            // Set delegate and use the default dispatch queue to execute the call back
            captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
            captureMetadataOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.qr]
            
            //Initialise the video preview layer and add it as a sublayer to the viewPreview view's layer
            DispatchQueue.main.async {
                self.previewLayer = AVCaptureVideoPreviewLayer(session: self.session)
                self.previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
                self.previewLayer.frame = self.layer.bounds
                self.layer.addSublayer(self.previewLayer)
                //start video capture
                DispatchQueue.global(qos: .background).async {
                    self.session.startRunning()
                }
               
            }

        } catch {
            //If any error occurs, simply print it out
            print(error)
            return
        }
        
    }
    
    /// 旋转方向
    func getCaptureVideoOrientation() -> AVCaptureVideoOrientation {
        switch UIDevice.current.orientation {
        case .portrait,.faceUp,.faceDown:
            return .portrait
        case .portraitUpsideDown: // 如果这里设置成AVCaptureVideoOrientationPortraitUpsideDown,则视频方向和拍摄时的方向是相反的。
            return .portrait
        case .landscapeLeft:
            return .landscapeRight
        case .landscapeRight:
            return .landscapeLeft
        default:
            return .portrait
        }
    }
    
    func checkCameraPermission() -> Bool {
        let authStatus = AVCaptureDevice.authorizationStatus(for: .video)
        if authStatus == .denied {
            
            return false
        }
        return true
    }
    
}

extension CustomCameraView:AVCaptureVideoDataOutputSampleBufferDelegate{
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
      
    }
}
extension CustomCameraView : AVCapturePhotoCaptureDelegate {
    func photoOutput(_ captureOutput: AVCapturePhotoOutput,
                 didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?,
                 previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?,
                 resolvedSettings: AVCaptureResolvedPhotoSettings,
                 bracketSettings: AVCaptureBracketedStillImageSettings?,
                 error: Error?) {
    
    }
    
    func photoOutput(_ output: AVCapturePhotoOutput, willCapturePhotoFor resolvedSettings: AVCaptureResolvedPhotoSettings) {
        AudioServicesDisposeSystemSoundID(1108)
    }
}
extension CustomCameraView : AVCaptureMetadataOutputObjectsDelegate {
    func metadataOutput(_ captureOutput: AVCaptureMetadataOutput,
                       didOutput metadataObjects: [AVMetadataObject],
                       from connection: AVCaptureConnection) {
        // Check if the metadataObjects array is contains at least one object.
        
    }
}


extension UIInterfaceOrientation {
    var videoOrientation: AVCaptureVideoOrientation? {
        switch self {
        case .portraitUpsideDown: return .portraitUpsideDown
        case .landscapeRight: return .landscapeRight
        case .landscapeLeft: return .landscapeLeft
        case .portrait: return .portrait
        default: return nil
        }
    }
}
